﻿using System;
using System.Text;

namespace Esponce.QRCode.Content
{
	/// <summary>
	/// Builder and parser for BIZCARD format - a de-facto standard for QR Code business cards.
	/// </summary>
	/// <remarks>
	/// Sample:
	/// BIZCARD:N:Monkey;X:Esponce;T:Code Monkey;C:Esponce;A:432 Sherwood Circle, Lake Charles, LA 70601;B:+15551234560;E:monkey@esponce.com;; 
	/// </remarks>
	public class BizcardContentFormat : ContentFormatBase<BizcardContentFormat>, IContactContentFormat
	{
		#region Public properties
		public string Name
		{
			get
			{
				return string.Format("{0} {1}", this.FirstName, this.LastName).Trim();
			}
		}

		public string FirstName
		{
			get
			{
				return this.firstName;
			}
			set
			{
				if (this.firstName != value)
				{
					this.firstName = value;
					OnPropertyChanged("FirstName");
					OnPropertyChanged("Name");
				}
			}
		}
		private string firstName;

		public string LastName
		{
			get
			{
				return this.lastName;
			}
			set
			{
				if (this.lastName != value)
				{
					this.lastName = value;
					OnPropertyChanged("LastName");
					OnPropertyChanged("Name");
				}
			}
		}
		private string lastName;

		public string CompanyName
		{
			get
			{
				return this.companyName;
			}
			set
			{
				if (this.companyName != value)
				{
					this.companyName = value;
					OnPropertyChanged("CompanyName");
				}
			}
		}
		private string companyName;

		public string JobTitle
		{
			get
			{
				return this.jobTitle;
			}
			set
			{
				if (this.jobTitle != value)
				{
					this.jobTitle = value;
					OnPropertyChanged("JobTitle");
				}
			}
		}
		private string jobTitle;

		public string FullAddress
		{
			get
			{
				if (!string.IsNullOrEmpty(this.fullAddress))
				{
					return this.fullAddress;
				}

				var builder = new StringBuilder();

				if (!string.IsNullOrEmpty(this.Address) && this.Address != ";") //";" is work-around for empty field in web interface
				{
					builder.Append(builder.Length > 0 ? ", " : "").Append(this.Address);
				}
				if (!string.IsNullOrEmpty(this.ZipCode) && this.ZipCode != ";")
				{
					builder.Append(builder.Length > 0 ? ", " : "").Append(this.ZipCode);
				}
				if (!string.IsNullOrEmpty(this.City) && this.City != ";")
				{
					builder.Append(builder.Length > 0 ? ", " : "").Append(this.City);
				}
				if (!string.IsNullOrEmpty(this.State) && this.State != ";")
				{
					builder.Append(builder.Length > 0 ? ", " : "").Append(this.State);
				}
				if (!string.IsNullOrEmpty(this.Country) && this.Country != ";")
				{
					builder.Append(builder.Length > 0 ? ", " : "").Append(this.Country);
				}

				string result = builder.ToString();
				return !string.IsNullOrEmpty(result) ? result : null;
			}
			set
			{
				//Can be reliably done in reverse direction?
				this.fullAddress = value;
			}
		}
		private string fullAddress = null;

		public string Address
		{
			get
			{
				return this.address;
			}
			set
			{
				if (this.address != value)
				{
					this.address = value;
					OnPropertyChanged("Address");
					OnPropertyChanged("FullAddress");
				}
			}
		}
		private string address;

		public string City
		{
			get
			{
				return this.city;
			}
			set
			{
				if (this.city != value)
				{
					this.city = value;
					OnPropertyChanged("City");
					OnPropertyChanged("FullAddress");
				}
			}
		}
		private string city;

		public string ZipCode
		{
			get
			{
				return this.zipCode;
			}
			set
			{
				if (this.zipCode != value)
				{
					this.zipCode = value;
					OnPropertyChanged("ZipCode");
					OnPropertyChanged("FullAddress");
				}
			}
		}
		private string zipCode;

		public string State
		{
			get
			{
				return this.state;
			}
			set
			{
				if (this.state != value)
				{
					this.state = value;
					OnPropertyChanged("State");
					OnPropertyChanged("FullAddress");
				}
			}
		}
		private string state;

		public string Country
		{
			get
			{
				return this.country;
			}
			set
			{
				if (this.country != value)
				{
					this.country = value;
					OnPropertyChanged("Country");
					OnPropertyChanged("FullAddress");
				}
			}
		}
		private string country;

		public string PhoneNumber
		{
			get
			{
				return this.phoneNumber;
			}
			set
			{
				if (this.phoneNumber != value)
				{
					this.phoneNumber = value;
					OnPropertyChanged("PhoneNumber");
				}
			}
		}
		private string phoneNumber;

		public string EmailAddress
		{
			get
			{
				return this.emailAddress;
			}
			set
			{
				if (this.emailAddress != value)
				{
					this.emailAddress = value;
					OnPropertyChanged("EmailAddress");
				}
			}
		}
		private string emailAddress;

		/// <summary>
		/// Gets or sets website URL. Note that this field is not used by BIZCARD but is required by IContactContentFormat.
		/// </summary>
		public string WebsiteUrl
		{
			get
			{
				return this.websiteUrl;
			}
			set
			{
				if (this.websiteUrl != value)
				{
					this.websiteUrl = value;
					OnPropertyChanged("WebsiteUrl");
				}
			}
		}
		private string websiteUrl;

		public string FullName
		{
			get
			{
				return string.Format("{0} {1}", this.FirstName, this.LastName).Trim();
			}
		}

		public string DisplayName
		{
			get
			{
				return this.FullName;
			}
		}
		#endregion

		#region Public methods
		public override void Parse(string content)
		{
			base.Parse(content);

			var helper = new ContentFormatHelper();
			string tag = helper.GetInlineTagName(content);
			if (tag != "BIZCARD")
			{
				throw new Exception("Missing 'BIZCARD' tag!");
			}

			var dictionary = helper.ParseInline(content);
			foreach (var item in dictionary)
			{
				string key = item.Key;
				string value = item.Value;

				switch (key)
				{
					case "N":
						this.FirstName = value;
						break;

					case "X":
						this.LastName = value;
						break;

					case "T":
						this.JobTitle = value;
						break;

					case "C":
						this.CompanyName = value;
						break;

					case "A":
						this.FullAddress = value;
						break;

					case "B":
						this.PhoneNumber = value;
						break;

					case "E":
						this.EmailAddress = value;
						break;
				}
			}
		}

		public override string Build()
		{
			var builder = new StringBuilder();
			builder.Append("BIZCARD:");

			if (!string.IsNullOrEmpty(this.FirstName))
			{
				builder.Append("N:").Append(this.FirstName).Append(";");
			}

			if (!string.IsNullOrEmpty(this.LastName))
			{
				builder.Append("X:").Append(this.LastName).Append(";");
			}

			if (!string.IsNullOrEmpty(this.JobTitle))
			{
				builder.Append("T:").Append(this.JobTitle).Append(";");
			}

			if (!string.IsNullOrEmpty(this.CompanyName))
			{
				builder.Append("C:").Append(this.CompanyName).Append(";");
			}

			if (!string.IsNullOrEmpty(this.FullAddress))
			{
				builder.Append("A:").Append(this.FullAddress).Append(";");
			}

			if (!string.IsNullOrEmpty(this.PhoneNumber))
			{
				builder.Append("B:").Append(this.PhoneNumber).Append(";");
			}

			if (!string.IsNullOrEmpty(this.EmailAddress))
			{
				builder.Append("E:").Append(this.EmailAddress).Append(";");
			}

			return builder.Append(";").ToString();
		}

		public override string GetFriendlyName()
		{
			return this.FullName ?? this.EmailAddress ?? this.PhoneNumber;
		}
		#endregion
	}
}
